// 内层作用域覆盖外层作用域
var tmp = new Date();

function f(){
  console.log(tmp);
  if (false){
    var tmp = "hello world";  // 变量提升了，没有赋值
  }
}

f(); // 没有输出

// 循环变量变为全局变量
var s = 'hello';

for (var i = 0; i < s.length; i++){
  console.log(s[i]);
}

console.log(i); // 5

// 块级作用域的存在可以使得外层代码块不受内层影响
function f1() {
  let n = 5;
  if (true) {
    let n = 10;
  }
  console.log(n); // 5
}

// 块级作用域的出现使得自执行函数不再需要了
// IIFE写法
(function () {
  var tmp = 1;
}());

// 块级作用域写法
{
  let tmp = 1;
}

// 函数本身的作用域在其块级作用域内，es5会把函数声明提升到当前作用域顶部
function f1() { console.log('I am outside!'); }
(function () {
  if(false) {
    // 重复声明一次函数f
    function f1() { console.log('I am inside!'); }
  }

  f1();
}());

// 需要注意的是，如果在严格模式下，函数只能在顶层作用域和函数内声明，其他情况（比如if代码块、循环代码块）的声明都会报错。
// 块级作用域的出现目的大致和let一致，为了解决js作用域混乱造成的不必要的错误